package com.example.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.example.config.AliConfig;
import com.example.model.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RequestMapping("/alipay")
@RestController
public class AliPayController {

  private static final Logger log = LoggerFactory.getLogger(AliPayController.class);
  @Autowired
  private AliConfig aliConfig;
  // 回调接口需要外网访问，建议本地开启内网穿透
  private static final String ALIPAY_NOTIFY_URL = "https://60155d5f.r26.cpolar.top/notify";

  /**
   * 创建免押订单接口
   */
  @RequestMapping("/freeze")
  public String freeze() throws AlipayApiException {

    String OutOrderNo = System.currentTimeMillis() + "";
    String OutRequestNo = System.currentTimeMillis() + "";

    // 构造client
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayFundAuthOrderAppFreezeRequest request = new AlipayFundAuthOrderAppFreezeRequest();
    AlipayFundAuthOrderAppFreezeModel model = new AlipayFundAuthOrderAppFreezeModel();

    // 设置订单标题
    model.setOrderTitle("租车押金");

    // 设置商户授权资金订单号
    model.setOutOrderNo(OutOrderNo);

    // 设置商户本次资金操作的请求流水号
    model.setOutRequestNo(OutRequestNo);

    // 设置需要冻结的金额
    model.setAmount("0.01");

    // 设置预授权订单相对超时时间
    model.setTimeoutExpress("2d");

    // 设置销售产品码
    model.setProductCode("PRE_AUTH_ONLINE");

    // 设置业务扩展参数       CREDIT_RENT_OFFLINE:线下物品租赁    支付宝类目地址：https://opendocs.alipay.com/open/062m0t
    model.setExtraParam("{\"category\": \"CREDIT_RENT_OFFLINE\",\"serviceId\": \"信誉服务id\"}");

    // 设置免押受理台模式
    model.setDepositProductMode("DEPOSIT_ONLY");

    request.setBizModel(model);
    request.setNotifyUrl(ALIPAY_NOTIFY_URL);
    // 发送请求
    AlipayFundAuthOrderAppFreezeResponse response = alipayClient.sdkExecute(request);
    log.info("线上资金授权冻结接口:{}", response.getBody());
    return response.getBody();
  }

  /**
   * 发起扣款接口 alipay.trade.pay
   * bizContent和BizModel不能同时使用，model未封装enable_pay_channels参数
   */
  @RequestMapping("/pay")
  public R<JSONObject> pay(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradePayRequest request = new AlipayTradePayRequest();

    JSONObject bizContent = new JSONObject();
    // 商家自定义订单号
    bizContent.put("out_trade_no", params.get("outTradeNo"));
    // 创建免押订单接口freeze回调接口返回内容中的auth_no
    bizContent.put("auth_no", params.get("authNo"));
    // 指定付款方式为余额支付，关闭交易场景
    // bizContent.put("enable_pay_channels", "balance");
    bizContent.put("product_code", "PREAUTH_PAY");
    bizContent.put("total_amount", "0.01");
    bizContent.put("subject", "租车租金");
    bizContent.put("auth_confirm_mode", "COMPLETE");
    request.setBizContent(bizContent.toString());
    request.setNotifyUrl(ALIPAY_NOTIFY_URL);
    AlipayTradePayResponse response = alipayClient.certificateExecute(request);
    JSONObject jsonObject = JSONObject.parseObject(response.getBody());
    log.info("发起扣款接口参数:{}", response.getBody());
    return R.ok(jsonObject);
  }

  /**
   * 资金授权解冻接口 alipay.fund.auth.order.unfreeze
   * 以authNo为准，OutRequestNo随便填 如报错参数异常或参数缺失则是某次请求已经使用过该OutRequestNo
   */

  @RequestMapping("/unfreeze")
  public String unfreeze(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());
    // 构造请求参数以调用接口
    AlipayFundAuthOrderUnfreezeRequest request = new AlipayFundAuthOrderUnfreezeRequest();
    AlipayFundAuthOrderUnfreezeModel model = new AlipayFundAuthOrderUnfreezeModel();

    // 设置支付宝资金授权订单号
    model.setAuthNo(params.get("authNo"));

    // 设置解冻请求流水号 确保不重复
    model.setOutRequestNo(params.get("outRequestNo"));

    // 设置本次操作解冻的金额
    model.setAmount("0.01");

    // 设置商户对本次解冻操作的附言描述
    model.setRemark("2025-08期解冻0.01元");

    request.setBizModel(model);

    AlipayFundAuthOrderUnfreezeResponse response = alipayClient.certificateExecute(request);
    log.info("response:{}", response.getBody());

    return response.getBody();
  }

  /**
   * 统一收单交易关闭接口 alipay.trade.close
   * 用于关闭支付余额不足时的订单
   */
  @RequestMapping("/close")
  public String close(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
    AlipayTradeCloseModel model = new AlipayTradeCloseModel();

    // 设置该交易在支付宝系统中的交易流水号
    model.setTradeNo(params.get("tradeNo"));

    request.setBizModel(model);

    AlipayTradeCloseResponse response = alipayClient.certificateExecute(request);
    System.out.println(response.getBody());
    return response.getBody();
  }

  /**
   * 统一收单交易退款接口 alipay.trade.refund
   * 可终止免押订单和已支付订单
   */

  @RequestMapping("/refund")
  public R refund(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    AlipayTradeRefundModel model = new AlipayTradeRefundModel();
    // 设置商家订单号
    model.setOutTradeNo(params.get("outTradeNo"));
    // 设置退款金额
    model.setRefundAmount("0.01");
    // 设置退款原因说明
    model.setRefundReason("正常退款");
    request.setBizModel(model);
    AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
    log.info("交易退款:{}", response.getBody());
    return R.ok(response.getBody());
  }

  /**
   * 完结免押订单接口
   * 资金授权撤销接口 alipay.fund.auth.operation.cancel
   * 此接口可以关闭免押订单和逾期订单，参数可以在芝麻免押下单成功记录获取
   */
  @RequestMapping("/cancel")
  public String cancel(@RequestBody Map<String, String> params) throws AlipayApiException {
    AlipayClient alipayClient = new DefaultAlipayClient(aliConfig.getConfig());

    // 构造请求参数以调用接口
    AlipayFundAuthOperationCancelRequest request = new AlipayFundAuthOperationCancelRequest();
    AlipayFundAuthOperationCancelModel model = new AlipayFundAuthOperationCancelModel();

    // 支付宝订单号
    model.setOperationId(params.get("operationId"));
    // 授权号
    model.setAuthNo(params.get("authNo"));
    model.setRemark("撤销授权");
    request.setBizModel(model);
    AlipayFundAuthOperationCancelResponse response = alipayClient.certificateExecute(request);
    return response.getBody();
  }

}
